import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

class HeroListDemo extends StatelessWidget {
  const HeroListDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    timeDilation = 1.0;
    return Scaffold(
      appBar: AppBar(
        title: Text('Hero List'),
        brightness: Brightness.dark,
      ),
      body: ListView.builder(
        itemBuilder: (_, index) {
          return HeroListItem(
            heroTag: 'tag_$index',
            content: '这是第$index个元素',
            assetImageName:
                index % 2 == 0 ? 'images/beauty.jpeg' : 'images/beauty2.jpeg',
            imageBgColor: index % 2 == 0 ? Colors.blue : Colors.green,
          );
        },
        shrinkWrap: true,
        scrollDirection: Axis.vertical,
        itemCount: 10,
        itemExtent: 110.0,
      ),
    );
  }
}

class HeroListItem extends StatelessWidget {
  final String heroTag;
  final assetImageName;
  final String content;
  final Color imageBgColor;
  const HeroListItem({
    Key? key,
    required this.heroTag,
    required this.content,
    required this.assetImageName,
    required this.imageBgColor,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        padding: EdgeInsets.fromLTRB(0, 10.0, 10.0, 10.0),
        child: Row(
          children: [
            Hero(
              tag: heroTag,
              createRectTween: (begin, end) {
                return ListToDetailRectTween(
                  begin: begin!,
                  end: end!,
                );
              },
              child: ListImage(
                assetImageName: assetImageName,
                imageBgColor: imageBgColor,
              ),
            ),
            SizedBox(
              width: 10.0,
            ),
            Expanded(
              child: Text(
                content,
                style: TextStyle(
                  color: Colors.black87,
                  fontSize: 18.0,
                ),
                maxLines: 2,
              ),
            ),
          ],
        ),
      ),
      onTap: () {
        Navigator.of(context).push(
          MaterialPageRoute(
            fullscreenDialog: true,
            builder: (context) => ListDetail(
              heroTag: heroTag,
              imageBgColor: imageBgColor,
              assetImageName: assetImageName,
            ),
          ),
        );
      },
    );
  }
}

class ListImage extends StatelessWidget {
  final imageBgColor;
  final assetImageName;
  const ListImage({
    Key? key,
    required this.imageBgColor,
    required this.assetImageName,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Container(
          height: 90.0,
          width: 110,
          decoration: BoxDecoration(
            color: imageBgColor,
            borderRadius: BorderRadius.only(
              topRight: Radius.circular(45.0),
              bottomRight: Radius.circular(45.0),
            ),
          ),
        ),
        Positioned(
          child: OvalImage(
            assetImageName: assetImageName,
            imageSize: 90.0,
          ),
          left: 20.0,
          top: 0.0,
        )
      ],
    );
  }
}

class OvalImage extends StatelessWidget {
  final assetImageName;
  final imageSize;
  const OvalImage(
      {Key? key, required this.assetImageName, required this.imageSize})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ClipOval(
      child: Image.asset(
        assetImageName,
        width: imageSize,
        height: imageSize,
      ),
    );
  }
}

class ListDetail extends StatelessWidget {
  final heroTag;
  final imageBgColor;
  final assetImageName;
  const ListDetail({
    Key? key,
    required this.heroTag,
    required this.imageBgColor,
    required this.assetImageName,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverToBoxAdapter(
          child: ListDetailHeader(
            heroTag: heroTag,
            imageBgColor: imageBgColor,
            assetImageName: assetImageName,
          ),
        ),
        SliverToBoxAdapter(
          child: Container(
            padding: EdgeInsets.all(20.0),
            color: Colors.white,
            height: MediaQuery.of(context).size.height - 160.0,
            child: Material(
              color: Colors.transparent,
              child: Text(
                '这是详情页面，文字会有很多！',
                style: TextStyle(
                  fontSize: 14.0,
                  color: Colors.black87,
                ),
              ),
            ),
          ),
        ),
      ],
      shrinkWrap: true,
    );
  }
}

class ListDetailHeader extends StatelessWidget {
  final heroTag;
  final imageBgColor;
  final assetImageName;
  const ListDetailHeader({
    Key? key,
    required this.heroTag,
    required this.imageBgColor,
    required this.assetImageName,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Hero(
      child: Stack(
        children: [
          Container(
            height: 160.0,
            width: double.infinity,
            decoration: BoxDecoration(
              color: imageBgColor,
            ),
          ),
          Positioned(
            child: Material(
              child: IconButton(
                icon: Icon(
                  Icons.close,
                  color: Colors.white,
                ),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
              color: Colors.transparent,
            ),
            left: 10.0,
            top: 50.0,
            height: 40.0,
          ),
          Positioned(
            child: OvalImage(
              assetImageName: assetImageName,
              imageSize: 90.0,
            ),
            right: 20.0,
            top: 50.0,
          ),
          Positioned(
            child: Material(
              color: Colors.transparent,
              child: Text(
                '这是详情',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 18.0,
                ),
                maxLines: 1,
              ),
            ),
            left: 20,
            top: 100,
          ),
        ],
      ),
      tag: heroTag,
      createRectTween: (begin, end) {
        return ListToDetailRectTween(
          begin: begin!,
          end: end!,
        );
      },
    );
  }
}

class ListToDetailRectTween extends RectTween {
  final Rect begin;
  final Rect end;

  ListToDetailRectTween({required this.begin, required this.end})
      : super(begin: begin, end: end);

  @override
  Rect lerp(double t) {
    if (t <= 0.5) {
      return Rect.fromLTRB(
        _rectMove(begin.left, end.left, 2 * t),
        _rectMove(begin.top, begin.top, 1.0),
        _rectMove(begin.right, end.right, 2 * t),
        _rectMove(begin.bottom, begin.bottom, 1.0),
      );
    } else {
      return Rect.fromLTRB(
        _rectMove(end.left, end.left, 1.0),
        _rectMove(begin.top, end.top, t),
        _rectMove(end.right, end.right, 1.0),
        _rectMove(begin.bottom, end.bottom, t),
      );
    }
  }

  double _rectMove(double begin, double end, double t) {
    return begin * (1 - t) + end * t;
  }
}
